
%{

#include <string>
#include <cffformat.h>
#include <iostream>
int yyerror(const char *s);
int yylex(void);

using namespace std;
extern cffNode* global_ast_node;
static cffNode*	parent_node = 0;
%}

%union{
	struct
	{
		cffNode	*node;
		struct
		{
			char *text;
		} lexVal;
	};
}

%start	input


%token  <lexVal>    IDENTIFIER
%token  <lexVal>    COMPLEX_IDENTIFIER
%token	<lexVal>		STRING_CONST
%token  <lexVal>    BLOCK_OPEN
%token  <lexVal>    BLOCK_CLOSE
%token  <lexVal>    ARROW_OPEN
%token  <lexVal>    ARROW_CLOSE
%token	<lexVal>		SEMICOLON
%token	<lexVal>		COLON
%token	<lexVal>		ASSIGN



%type   <node>			input;
%type   <node>			nodes;
%type   <node>			node;
%type   <node>			node_close;
%type		<node>			attributes_def;
%type		<node>			attributes;
%type		<node>			attribute;

%%

input
		: { parent_node = global_ast_node; } nodes { }

nodes
		: { }
		| node nodes { }
		;

node
		: IDENTIFIER { cffNode* node = new cffNode (); node->SetName ($1.text); free($1.text); parent_node->AddNode (node); node->Release (); parent_node = node; }
				attributes_def node_close { parent_node = parent_node->GetParent (); }
		;

node_close
		: SEMICOLON {}
		| BLOCK_OPEN nodes BLOCK_CLOSE {}
		;

attributes_def
		:  { }
		| ARROW_OPEN attributes ARROW_CLOSE { }
		| COLON attributes { }
		;

attributes
		: attribute more_attributes { } 
		;

more_attributes
		: { }
		| attributes { }
		;
		
attribute
		: IDENTIFIER								{ parent_node->GetAttributes ().AddAttribute ($1.text); free($1.text); }
		| COMPLEX_IDENTIFIER						{ parent_node->GetAttributes ().AddAttribute ($1.text); free($1.text); }
		| STRING_CONST								{ parent_node->GetAttributes ().AddAttribute ($1.text); free($1.text); }
		| IDENTIFIER ASSIGN IDENTIFIER				{ parent_node->GetAttributes ().SetAttribute ($1.text, $3.text); free($1.text); free($3.text); }
		| IDENTIFIER ASSIGN COMPLEX_IDENTIFIER		{ parent_node->GetAttributes ().SetAttribute ($1.text, $3.text); free($1.text); free($3.text); }
		| IDENTIFIER ASSIGN STRING_CONST			{ parent_node->GetAttributes ().SetAttribute ($1.text, $3.text); free($1.text); free($3.text); }
		;
%%

int yyerror(const char* s)
{
		extern int yylineno;	// defined and maintained in lex.c
		extern char *yytext;	// defined and maintained in lex.c

		cerr << "ERROR: " << std::string(s) << " at symbol \"" << yytext;
		cerr << "\" on line " << (yylineno+1) << endl;
	return 1;
}


/* vim:set ts=2 sw=2 noet */
